<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 14.5.&nbsp; I/O Multiplexing</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch14lev1sec4.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch14lev1sec6.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top"><a name="ch14lev1sec5"></a>
<h3 class="docSection1Title">14.5. I/O Multiplexing</h3>
<p class="docText">When we read from one descriptor and write to another, we can use blocking I/O in a loop, such as</P>

<pre>
        while ((n = read(STDIN_FILENO, buf, BUFSIZ)) &gt; 0)
            if (write(STDOUT_FILENO, buf, n) != n)
                err_sys("write error");
</pre><BR>

<p class="docText">We see this form of blocking I/O over and over again. What if we have to read from two descriptors? In this case, we can't do a blocking <tt>read</tt> on either descriptor, as data may appear on one descriptor while we're blocked in a <tt>read</tt> on the other. A different technique is required to handle this case.</p>
<p class="docText">Let's look at the structure of the <tt>telnet</tt>(1) command. In this program, we read from the terminal (standard input) and write to a network connection, and we read from the network connection and write to the terminal (standard output). At the other end of the network connection, the <tt>telnetd</tt> daemon reads what we typed and presents it to a shell as if we were logged in to the remote machine. The <tt>telnetd</tt> daemon sends any output generated by the commands we type back to us through the <tt>telnet</tt> command, to be displayed on our terminal. <a class="docLink" href="#ch14fig20">Figure 14.20</a> shows a picture of this.</P>
<a name="ch14fig20"></a><P><center>
<H5 class="docFigureTitle">Figure 14.20. Overview of <tt>telnet</tt> program</h5>

<p class="docText">
<img border="0" alt="" id="195131139046" width="430" height="70" SRC="images/0201433079/graphics/14fig20.gif;423615"></P>

</center></P><BR>
<p class="docText">The <tt>telnet</tt> process has two inputs and two outputs. We can't do a blocking <tt>read</tt> on either of the inputs, as we never know which input will have data for us.</p>
<p class="docText"><a name="idd1e103807"></a><a name="idd1e103810"></a><a name="idd1e103813"></a><a name="idd1e103818"></a><a name="idd1e103823"></a><a name="idd1e103828"></a><a name="idd1e103831"></a><a name="idd1e103836"></a><a name="idd1e103841"></a><a name="idd1e103846"></a><a name="idd1e103851"></a><a name="idd1e103854"></a><a name="idd1e103857"></a>One way to handle this particular problem is to divide the process in two pieces (using <tt>fork</tt>), with each half handling one direction of data. We show this in <a class="docLink" href="#ch14fig21">Figure 14.21</a>. (The <tt>cu</tt>(1) command provided with System V's <tt>uucp</tt> communication package was structured like this.)</P>
<a name="ch14fig21"></a><p><center>
<H5 class="docFigureTitle">Figure 14.21. The <tt>telnet</tt> program using two processes</H5>

<p class="docText">
<img border="0" alt="" id="195131139046" width="430" height="137" SRC="images/0201433079/graphics/14fig21.gif;423615"></P>

</center></p><BR>
<p class="docText">If we use two processes, we can let each process do a blocking <tt>read</tt>. But this leads to a problem when the operation terminates. If an end of file is received by the child (the network connection is disconnected by the <tt>telnetd</tt> daemon), then the child terminates, and the parent is notified by the <tt>SIGCHLD</tt> signal. But if the parent terminates (the user enters an end of file at the terminal), then the parent has to tell the child to stop. We can use a signal for this (<tt>SIGUSR1</tt>, for example), but it does complicate the program somewhat.</P>
<p class="docText">Instead of two processes, we could use two threads in a single process. This avoids the termination complexity, but requires that we deal with synchronization between the threads, which could add more complexity than it saves.</p>
<p class="docText">We could use nonblocking I/O in a single process by setting both descriptors nonblocking and issuing a <tt>read</tt> on the first descriptor. If data is present, we read it and process it. If there is no data to read, the call returns immediately. We then do the same thing with the second descriptor. After this, we wait for some amount of time (a few seconds, perhaps) and then try to read from the first descriptor again. This type of loop is called <span class="docEmphasis">polling</span>. The problem is that it wastes CPU time. Most of the time, there won't be data to read, so we waste time performing the <tt>read</tt> system calls. We also have to guess how long to wait each time around the loop. Although it works on any system that supports nonblocking I/O, polling should be avoided on a multitasking system.</P>
<p class="docText">Another technique is called <span class="docEmphasis">asynchronous I/O</span>. To do this, we tell the kernel to notify us with a signal when a descriptor is ready for I/O. There are two problems with this. First, not all systems support this feature (it is an optional facility in the Single UNIX Specification). System V provides the <tt>SIGPOLL</tt> signal for this technique, but this signal works only if the descriptor refers to a STREAMS device. BSD has a similar signal, <tt>SIGIO</tt>, but it has similar limitations: it works only on descriptors that refer to terminal devices or networks. The second problem with this technique is that there is only one of these signals per process (<tt>SIGPOLL</tt> or <tt>SIGIO</tt>). If we enable this signal for two descriptors (in the example we've been talking about, reading from two descriptors), the occurrence of the signal doesn't tell us which descriptor is ready. To determine which descriptor is ready, we still need to set each nonblocking and try them in sequence. We describe asynchronous I/O briefly in <a class="docLink" href="ch14lev1sec6.html#ch14lev1sec6">Section 14.6</a>.</P>
<p class="docText"><a name="idd1e103949"></a><a name="idd1e103952"></a><a name="idd1e103955"></a><a name="idd1e103958"></a><a name="idd1e103961"></a><a name="idd1e103966"></a><a name="idd1e103971"></a><a name="idd1e103976"></a><a name="idd1e103979"></a><a name="idd1e103982"></a><a name="idd1e103985"></a><a name="idd1e103990"></a><a name="idd1e103995"></a><a name="idd1e104000"></a><a name="idd1e104005"></a>A better technique is to use <span class="docEmphasis">I/O multiplexing</span>. To do this, we build a list of the descriptors that we are interested in (usually more than one descriptor) and call a function that doesn't return until one of the descriptors is ready for I/O. On return from the function, we are told which descriptors are ready for I/O.</p>
<p class="docText">Three functions<tt>poll</tt>, <tt>pselect</tt>, and <tt>select</tt>allow us to perform I/O multiplexing. <a class="docLink" href="#ch14fig22">Figure 14.22</a> summarizes which platforms support them. Note that <tt>select</tt> is defined by the base POSIX.1 standard, but <tt>poll</tt> is an XSI extension to the base.</p>
<a name="ch14fig22"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><h5 class="docTableTitle">Figure 14.22. I/O multiplexing supported by various UNIX systems</H5></caption><colgroup><col width="100"><col width="50"><col width="75"><col width="75"><col width="200"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="left" valign="top"><p class="docText"><span class="docEmphRoman">System</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman"><tt>poll</tt></span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman"><tt>pselect</tt></span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman"><tt>select</tt></span></p></th><th class="bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman"><tt>&lt;sys/select.h&gt;</tt></span></p></th></tr></thead><tr><td class="rightBorder bottomBorder" align="left" valign="top"><p class="docText">SUS</p></td><td class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">XSI</p></td><td class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="bottomBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD></tr><TR><TD class="rightBorder" align="left" valign="top"><p class="docText">FreeBSD 5.2.1</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="docTableCell" align="left" valign="top">&nbsp;</TD></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText">Linux 2.4.22</P></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText">Mac OS X 10.3</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="docTableCell" align="left" valign="top">&nbsp;</td></TR><TR><TD class="rightBorder" align="left" valign="top"><p class="docText">Solaris 9</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="left" valign="top">&nbsp;</td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></TD></tr></table></P><BR>
<blockquote>
<p class="docText">POSIX specifies that <tt>&lt;sys/select&gt;</tt> be included to pull the information for <tt>select</tt> into your program. Historically, however, we have had to include three other header files, and some of the implementations haven't yet caught up to the standard. Check the <tt>select</tt> manual page to see what your system supports. Older systems require that you include <tt>&lt;sys/types.h&gt;</tt>, <tt>&lt;sys/time.h&gt;</tt>, and <tt>&lt;unistd.h&gt;</tt>.</p>
<p class="docText">I/O multiplexing was provided with the <tt>select</tt> function in 4.2BSD. This function has always worked with any descriptor, although its main use has been for terminal I/O and network I/O. SVR3 added the <tt>poll</tt> function when the STREAMS mechanism was added. Initially, however, <tt>poll</tt> worked only with STREAMS devices. In SVR4, support was added to allow <tt>poll</tt> to work on any descriptor.</p>
</blockquote>
<a name="ch14lev2sec14"></a>
<h4 class="docSection2Title">14.5.1. <tt>select</tt> and <tt>pselect</tt> Functions</h4>
<p class="docText">The <tt>select</tt> function lets us do I/O multiplexing under all POSIX-compatible platforms. The arguments we pass to <tt>select</tt> tell the kernel</P>
<ul><LI><p class="docList">Which descriptors we're interested in.</p></LI><li><p class="docList">What conditions we're interested in for each descriptor. (Do we want to read from a given descriptor? Do we want to write to a given descriptor? Are we interested in an exception condition for a given descriptor?)</p></li><li><p class="docList">How long we want to wait. (We can wait forever, wait a fixed amount of time, or not wait at all.)</p></li></ul>
<p class="docText">On the return from <tt>select</tt>, the kernel tells us</p>
<ul><li><p class="docList">The total count of the number of descriptors that are ready</p></li><li><p class="docList">Which descriptors are ready for each of the three conditions (read, write, or exception condition)</p></li></ul>
<p class="docText"><a name="idd1e104300"></a><a name="idd1e104303"></a><a name="idd1e104308"></a><a name="idd1e104313"></a><a name="idd1e104318"></a><a name="idd1e104323"></a><a name="idd1e104328"></a><a name="idd1e104335"></a><a name="idd1e104340"></a><a name="idd1e104345"></a>With this return information, we can call the appropriate I/O function (usually <tt>read</tt> or <tt>write</tt>) and know that the function won't block.</p>
<a name="inta277"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><TR><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID1"></a><div class="v1"><a href="ch14lev1sec5.html#PLID1">[View full width]</a></div><pre>
#include &lt;sys/select.h&gt;

int select(int <span class="docEmphItalicAlt">maxfdp1</span>, fd_set *restrict <span class="docEmphItalicAlt">readfds</span>,
           fd_set *restrict <span class="docEmphItalicAlt">writefds</span>, fd_set
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> *restrict <span class="docEmphItalicAlt">exceptfds</span>,
           struct timeval *restrict <span class="docEmphItalicAlt">tvptr</span>);</pre><BR>
</P></TD></tr><TR><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: count of ready descriptors, 0 on timeout, 1 on error</P></td></TR></table></p><BR>
<p class="docText">Let's look at the last argument first. This specifies how long we want to wait:</P>

<pre>
   struct timeval {
     long tv_sec;     /* seconds */
     long tv_usec;    /* and microseconds */
   };
</pre><BR>

<p class="docText">There are three conditions.</p>

<pre>
   <span class="docEmphItalicAlt">tvptr</span> == NULL
</pre><BR>

<blockquote>
<p class="docText">Wait forever. This infinite wait can be interrupted if we catch a signal. Return is made when one of the specified descriptors is ready or when a signal is caught. If a signal is caught, <tt>select</tt> returns 1 with <tt>errno</tt> set to <tt>EINTR</tt>.</P>
</blockquote>

<pre>
   <span class="docEmphItalicAlt">tvptr-&gt;tv_sec</span> == 0 &amp;&amp; <span class="docEmphItalicAlt">tvptr-&gt;tv_usec</span> == 0
</pre><br>

<blockquote>
<p class="docText">Don't wait at all. All the specified descriptors are tested, and return is made immediately. This is a way to poll the system to find out the status of multiple descriptors, without blocking in the <tt>select</tt> function.</P>
</blockquote>

<pre>
   <span class="docEmphItalicAlt">tvptr-&gt;tv_sec</span> != 0 || <span class="docEmphItalicAlt">tvptr-&gt;tv_usec</span> != 0
</pre><BR>

<blockquote>
<p class="docText">Wait the specified number of seconds and microseconds. Return is made when one of the specified descriptors is ready or when the timeout value expires. If the timeout expires before any of the descriptors is ready, the return value is 0. (If the system doesn't provide microsecond resolution, the <span class="docEmphasis">tvptr&gt;tv_usec</span> value is rounded up to the nearest supported value.) As with the first condition, this wait can also be interrupted by a caught signal.</p>
<blockquote>
<p class="docText">POSIX.1 allows an implementation to modify the <tt>timeval</tt> structure, so after <tt>select</tt> returns, you can't rely on the structure containing the same values it did before calling <tt>select</tt>. FreeBSD 5.2.1, Mac OS X 10.3, and Solaris 9 all leave the structure unchanged, but Linux 2.4.22 will update it with the time remaining if <tt>select</tt> returns before the timeout value expires.</p>
</blockquote>
</blockquote>
<p class="docText">The middle three arguments<span class="docEmphasis">readfds</span>, <span class="docEmphasis">writefds</span>, and <span class="docEmphasis">exceptfds</span>are pointers to <span class="docEmphasis">descriptor sets</span>. These three sets specify which descriptors we're interested in and for which conditions (readable, writable, or an exception condition). A descriptor set is stored in an <tt>fd_set</tt> data type. This data type is chosen by the implementation so that it can hold one bit for each possible descriptor. We can consider it to be just a big array of bits, as shown in <a class="docLink" href="#ch14fig23">Figure 14.23</a>.</p>
<a name="ch14fig23"></a><p><center>
<H5 class="docFigureTitle">Figure 14.23. Specifying the read, write, and exception descriptors for <tt>select</tt></h5>

<p class="docText">
<img border="0" alt="" id="195131139046" width="475" height="218" SRC="images/0201433079/graphics/14fig23.gif;423615"></P>

</center></p><BR>
<p class="docText"><a name="idd1e104524"></a><a name="idd1e104529"></a><a name="idd1e104536"></a><a name="idd1e104541"></a><a name="idd1e104548"></a><a name="idd1e104553"></a><a name="idd1e104560"></a><a name="idd1e104565"></a>The only thing we can do with the <tt>fd_set</tt> data type is allocate a variable of this type, assign a variable of this type to another variable of the same type, or use one of the following four functions on a variable of this type.</p>
<a name="inta53"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
#include &lt;sys/select.h&gt;

int FD_ISSET(int <span class="docEmphItalicAlt">fd</span>, fd_set *<span class="docEmphItalicAlt">fdset</span>);</pre><br>
</p></td></tr><tr><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: nonzero if <span class="docEmphasis">fd</span> is in set, 0 otherwise</p></td></tr><tr><td class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
void FD_CLR(int <span class="docEmphItalicAlt">fd</span>, fd_set *<span class="docEmphItalicAlt">fdset</span>);
void FD_SET(int <span class="docEmphItalicAlt">fd</span>, fd_set *<span class="docEmphItalicAlt">fdset</span>);
void FD_ZERO(fd_set *<span class="docEmphasis">fdset</span>);
</pre><br>

</p></TD></TR></table></p><BR>
<p class="docText">These interfaces can be implemented as either macros or functions. An <tt>fd_set</tt> is set to all zero bits by calling <tt>FD_ZERO</tt>. To turn on a single bit in a set, we use <tt>FD_SET</tt>. We can clear a single bit by calling <tt>FD_CLR</tt>. Finally, we can test whether a given bit is turned on in the set with <tt>FD_ISSET</tt>.</P>
<p class="docText">After declaring a descriptor set, we must zero the set using <tt>FD_ZERO</tt>. We then set bits in the set for each descriptor that we're interested in, as in</P>

<pre>
   fd_set   rset;
   int      fd;

   FD_ZERO(&amp;rset);
   FD_SET(fd, &amp;rset);
   FD_SET(STDIN_FILENO, &amp;rset);
</pre><br>

<p class="docText">On return from <tt>select</tt>, we can test whether a given bit in the set is still on using <tt>FD_ISSET</tt>:</P>

<pre>
   if (FD_ISSET(fd, &amp;rset)) {
       ...
   }
</pre><BR>

<p class="docText"><a name="idd1e104677"></a><a name="idd1e104680"></a><a name="idd1e104685"></a><a name="idd1e104690"></a><a name="idd1e104695"></a>Any (or all) of the middle three arguments to <tt>select</tt> (the pointers to the descriptor sets) can be null pointers if we're not interested in that condition. If all three pointers are <tt>NULL</tt>, then we have a higher precision timer than provided by <tt>sleep</tt>. (Recall from <a class="docLink" href="ch10lev1sec19.html#ch10lev1sec19">Section 10.19</a> that <tt>sleep</tt> waits for an integral number of seconds. With <tt>select</tt>, we can wait for intervals less than 1 second; the actual resolution depends on the system's clock.) Exercise 14.6 shows such a function.</P>
<p class="docText">The first argument to <tt>select</tt>, <span class="docEmphasis">maxfdp1</span>, stands for &quot;maximum file descriptor plus 1.&quot; We calculate the highest descriptor that we're interested in, considering all three of the descriptor sets, add 1, and that's the first argument. We could just set the first argument to <tt>FD_SETSIZE</tt>, a constant in <tt>&lt;sys/select.h&gt;</tt> that specifies the maximum number of descriptors (often 1,024), but this value is too large for most applications. Indeed, most applications probably use between 3 and 10 descriptors. (Some applications need many more descriptors, but these UNIX programs are atypical.) By specifying the highest descriptor that we're interested in, we can prevent the kernel from going through hundreds of unused bits in the three descriptor sets, looking for bits that are turned on.</p>
<p class="docText">As an example, <a class="docLink" href="#ch14fig24">Figure 14.24</a> shows what two descriptor sets look like if we write</P>

<pre>
   fd_set readset, writeset;

   FD_ZERO(&amp;readset);
   FD_ZERO(&amp;writeset);
   FD_SET(0, &amp;readset);
   FD_SET(3, &amp;readset);
   FD_SET(1, &amp;writeset);
   FD_SET(2, &amp;writeset);
   select(4, &amp;readset, &amp;writeset, NULL, NULL);
</pre><br>

<a name="ch14fig24"></a><P><center>
<H5 class="docFigureTitle">Figure 14.24. Example descriptor sets for <tt>select</tt></H5>

<p class="docText">
<img border="0" alt="" id="195131139046" width="491" height="201" SRC="images/0201433079/graphics/14fig24.gif;423615"></p>

</center></P><BR>
<p class="docText">The reason we have to add 1 to the maximum descriptor number is that descriptors start at 0, and the first argument is really a count of the number of descriptors to check (starting with descriptor 0).</p>
<p class="docText">There are three possible return values from <tt>select</tt>.</P>
<div style="font-weight:bold"><ol class="docList" type="1"><LI><div style="font-weight:normal"><p class="docList">A return value of 1 means that an error occurred. This can happen, for example, if a signal is caught before any of the specified descriptors are ready. In this case, none of the descriptor sets will be modified.</p></div></li><li><div style="font-weight:normal"><p class="docList"><a name="idd1e104782"></a><a name="idd1e104787"></a><a name="idd1e104794"></a><a name="idd1e104799"></a><a name="idd1e104804"></a><a name="idd1e104807"></a><a name="idd1e104812"></a><a name="idd1e104817"></a>A return value of 0 means that no descriptors are ready. This happens if the time limit expires before any of the descriptors are ready. When this happens, all the descriptor sets will be zeroed out.</p></div></LI><li><div style="font-weight:normal"><p class="docList">A positive return value specifies the number of descriptors that are ready. This value is the sum of the descriptors ready in all three sets, so if the same descriptor is ready to be read <span class="docEmphasis">and</span> written, it will be counted twice in the return value. The only bits left on in the three descriptor sets are the bits corresponding to the descriptors that are ready.</P></div></li></ol></div>
<p class="docText">We now need to be more specific about what &quot;ready&quot; means.</P>
<ul><li><p class="docList">A descriptor in the read set (<span class="docEmphasis">readfds</span>) is considered ready if a <tt>read</tt> from that descriptor won't block.</p></li><li><p class="docList">A descriptor in the write set (<span class="docEmphasis">writefds</span>) is considered ready if a <tt>write</tt> to that descriptor won't block.</p></li><li><p class="docList">A descriptor in the exception set (<span class="docEmphasis">exceptfds</span>) is considered ready if an exception condition is pending on that descriptor. Currently, an exception condition corresponds to either the arrival of out-of-band data on a network connection or certain conditions occurring on a pseudo terminal that has been placed into packet mode. (<a class="docLink" href="ch15lev1sec10.html#ch15lev1sec10">Section 15.10</a> of Stevens [<a class="docLink" href="bib01.html#biblio01_058">1990</a>] describes this latter condition.)</p></li><li><p class="docList">File descriptors for regular files always return ready for reading, writing, and exception conditions.</p></li></ul>
<p class="docText">It is important to realize that whether a descriptor is blocking or not doesn't affect whether <tt>select</tt> blocks. That is, if we have a nonblocking descriptor that we want to read from and we call <tt>select</tt> with a timeout value of 5 seconds, <tt>select</tt> will block for up to 5 seconds. Similarly, if we specify an infinite timeout, <tt>select</tt> blocks until data is ready for the descriptor or until a signal is caught.</p>
<p class="docText">If we encounter the end of file on a descriptor, that descriptor is considered readable by <tt>select</tt>. We then call <tt>read</tt> and it returns 0, the way to signify end of file on UNIX systems. (Many people incorrectly assume that <tt>select</tt> indicates an exception condition on a descriptor when the end of file is reached.)</p>
<p class="docText">POSIX.1 also defines a variant of <tt>select</tt> called <tt>pselect</tt>.</p>
<a name="inta185"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><TR><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID11"></a><div class="v1"><a href="ch14lev1sec5.html#PLID11">[View full width]</a></div><pre>
#include &lt;sys/select.h&gt;

int pselect(int <span class="docEmphItalicAlt">maxfdp1</span>, fd_set *restrict <span class="docEmphItalicAlt">readfds</span>,
            fd_set *restrict <span class="docEmphItalicAlt">writefds</span>, fd_set
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> *restrict <span class="docEmphItalicAlt">exceptfds</span>,
            const struct timespec *restrict <span class="docEmphItalicAlt">tsptr</span>,
            const sigset_t *restrict <span class="docEmphItalicAlt">sigmask</span>);</pre><BR>
</P></TD></tr><TR><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: count of ready descriptors, 0 on timeout, 1 on error</P></td></TR></table></p><BR>
<p class="docText">The <tt>pselect</tt> function is identical to <tt>select</tt>, with the following exceptions.</P>
<UL><li><p class="docList">The timeout value for <tt>select</tt> is specified by a <tt>timeval</tt> structure, but for <tt>pselect</tt>, a <tt>timespec</tt> structure is used. (Recall the definition of the <tt>timespec</tt> structure in <a class="docLink" href="ch11lev1sec6.html#ch11lev1sec6">Section 11.6</a>.) Instead of seconds and microseconds, the <tt>timespec</tt> <a name="idd1e104999"></a><a name="idd1e105002"></a><a name="idd1e105007"></a><a name="idd1e105012"></a><a name="idd1e105019"></a><a name="idd1e105024"></a><a name="idd1e105029"></a><a name="idd1e105034"></a><a name="idd1e105037"></a><a name="idd1e105040"></a><a name="idd1e105043"></a><a name="idd1e105046"></a>structure represents the timeout value in seconds and nanoseconds. This provides a higher-resolution timeout if the platform supports that fine a level of granularity.</P></LI><li><p class="docList">The timeout value for <tt>pselect</tt> is declared <tt>const</tt>, and we are guaranteed that its value will not change as a result of calling <tt>pselect</tt>.</P></LI><li><p class="docList">An optional signal mask argument is available with <tt>pselect</tt>. If <span class="docEmphasis">sigmask</span> is null, <tt>pselect</tt> behaves as <tt>select</tt> does with respect to signals. Otherwise, <span class="docEmphasis">sigmask</span> points to a signal mask that is atomically installed when <tt>pselect</tt> is called. On return, the previous signal mask is restored.</p></li></ul>

<a name="ch14lev2sec15"></a>
<H4 class="docSection2Title">14.5.2. <tt>poll</tt> Function</h4>
<p class="docText">The <tt>poll</tt> function is similar to <tt>select</tt>, but the programmer interface is different. As we'll see, <tt>poll</tt> is tied to the STREAMS system, since it originated with System V, although we are able to use it with any type of file descriptor.</P>
<a name="inta180"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><TR><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID12"></a><div class="v1"><a href="ch14lev1sec5.html#PLID12">[View full width]</a></div><pre>
#include &lt;poll.h&gt;

int poll(struct pollfd <span class="docEmphItalicAlt">fdarray</span>[], nfds_t <span class="docEmphItalicAlt">nfds</span>, int
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> <span class="docEmphItalicAlt">timeout</span>);</pre><br>
</p></td></tr><tr><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: count of ready descriptors, 0 on timeout, 1 on error</p></td></tr></table></p><br>
<p class="docText">With <tt>poll</tt>, instead of building a set of descriptors for each condition (readability, writability, and exception condition), as we did with <tt>select</tt>, we build an array of <tt>pollfd</tt> structures, with each array element specifying a descriptor number and the conditions that we're interested in for that descriptor:</p>

<pre>
   struct pollfd {
     int   fd;       /* file descriptor to check, or &lt;0 to ignore */
     short events;   /* events of interest on fd */
     short revents;  /* events that occurred on fd */
   };
</pre><br>

<p class="docText">The number of elements in the <span class="docEmphasis">fdarray</span> array is specified by <span class="docEmphasis">nfds</span>.</p>
<blockquote>
<p class="docText">Historically, there have been differences in how the <span class="docEmphasis">nfds</span> parameter was declared. SVR3 specified the number of elements in the array as an <tt>unsigned long</tt>, which seems excessive. In the SVR4 manual [<a class="docLink" href="bib01.html#biblio01_010">AT&amp;T 1990d</a>], the prototype for <tt>poll</tt> showed the data type of the second argument as <tt>size_t</tt>. (Recall the primitive system data types, <a class="docLink" href="ch02lev1sec8.html#ch02fig20">Figure 2.20</a>.) But the actual prototype in the <tt>&lt;poll.h&gt;</tt> header still showed the second argument as an <tt>unsigned long</tt>. The Single UNIX Specification defines the new type <tt>nfds_t</tt> to allow the implementation to select the appropriate type and hide the details from applications. Note that this type has to be large enough to hold an integer, since the return value represents the number of entries in the array with satisfied events.</p>
<p class="docText">The SVID corresponding to SVR4 [<a class="docLink" href="bib01.html#biblio01_006">AT&amp;T 1989</a>] showed the first argument to <tt>poll</tt> as <tt>struct pollfd</tt> <span class="docEmphasis">fdarray</span><tt>[]</tt>, whereas the SVR4 manual page [<a class="docLink" href="bib01.html#biblio01_010">AT&amp;T 1990d</a>] showed this argument as <tt>struct pollfd *</tt><span class="docEmphasis">fdarray</span>. In the C language, both declarations are equivalent. We use the first declaration to reiterate that <tt>fdarray</tt> points to an array of structures and not a pointer to a single structure.</p>
</blockquote>
<p class="docText"><a name="idd1e105233"></a><a name="idd1e105238"></a><a name="idd1e105243"></a><a name="idd1e105248"></a><a name="idd1e105253"></a><a name="idd1e105258"></a><a name="idd1e105263"></a><a name="idd1e105268"></a><a name="idd1e105273"></a><a name="idd1e105278"></a><a name="idd1e105283"></a><a name="idd1e105288"></a><a name="idd1e105293"></a><a name="idd1e105298"></a>To tell the kernel what events we're interested in for each descriptor, we have to set the <tt>events</tt> member of each array element to one or more of the values in <a class="docLink" href="#ch14fig25">Figure 14.25</a>. On return, the <tt>revents</tt> member is set by the kernel, specifying which events have occurred for each descriptor. (Note that <tt>poll</tt> doesn't change the <tt>events</tt> member. This differs from <tt>select</tt>, which modifies its arguments to indicate what is ready.)</P>
<a name="ch14fig25"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><h5 class="docTableTitle">Figure 14.25. The <tt>events</tt> and <tt>revents</tt> flags for <tt>poll</tt></H5></caption><colgroup><col width="100"><col width="50"><col width="100"><col width="300"></colgroup><thead><TR><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Name</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Input to <tt>events</tt>?</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Result from <tt>revents</tt>?</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Description</span></P></th></TR></thead><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLIN</tt></p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="docTableCell" align="left" valign="top"><p class="docText">Data other than high priority can be read without blocking (equivalent to <tt>POLLRDNORM|POLLRDBAND</tt>).</P></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLRDNORM</tt></P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="left" valign="top"><p class="docText">Normal data (priority band 0) can be read without blocking.</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLRDBAND</tt></p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><TD class="docTableCell" align="left" valign="top"><p class="docText">Data from a nonzero priority band can be read without blocking.</P></td></TR><TR><TD class="rightBorder bottomBorder" align="left" valign="top"><p class="docText"><tt>POLLPRI</tt></p></TD><TD class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="bottomBorder" align="left" valign="top"><p class="docText">High-priority data can be read without blocking.</P></td></TR><TR><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLOUT</tt></P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="docTableCell" align="left" valign="top"><p class="docText">Normal data can be written without blocking.</p></TD></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLWRNORM</tt></p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="left" valign="top"><p class="docText">Same as <tt>POLLOUT</tt>.</p></td></tr><tr><td class="rightBorder bottomBorder" align="left" valign="top"><p class="docText"><tt>POLLWRBAND</tt></P></TD><td class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><TD class="rightBorder bottomBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="bottomBorder" align="left" valign="top"><p class="docText">Data for a nonzero priority band can be written without blocking.</P></td></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLERR</tt></P></TD><td class="rightBorder" align="left" valign="top">&nbsp;</TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="docTableCell" align="left" valign="top"><p class="docText">An error has occurred.</p></td></tr><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLHUP</tt></p></TD><td class="rightBorder" align="left" valign="top">&nbsp;</TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="left" valign="top"><p class="docText">A hangup has occurred.</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>POLLNVAL</tt></p></td><td class="rightBorder" align="left" valign="top">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="left" valign="top"><p class="docText">The descriptor does not reference an open file.</P></TD></tr></table></P><BR>
<p class="docText">The first four rows of <a class="docLink" href="#ch14fig25">Figure 14.25</a> test for readability, the next three test for writability, and the final three are for exception conditions. The last three rows in <a class="docLink" href="#ch14fig25">Figure 14.25</a> are set by the kernel on return. These three values are returned in <tt>revents</tt> when the condition occurs, even if they weren't specified in the <tt>events</tt> field.</P>
<p class="docText">When a descriptor is hung up (<tt>POLLHUP</tt>), we can no longer write to the descriptor. There may, however, still be data to be read from the descriptor.</p>
<p class="docText">The final argument to <tt>poll</tt> specifies how long we want to wait. As with <tt>select</tt>, there are three cases.</P>

<pre>
   <span class="docEmphItalicAlt">timeout</span> == -1
</pre><BR>

<blockquote>
<p class="docText">Wait forever. (Some systems define the constant <tt>INFTIM</tt> in <tt>&lt;stropts.h&gt;</tt> as 1.) We return when one of the specified descriptors is ready or when a signal is caught. If a signal is caught, <tt>poll</tt> returns 1 with <tt>errno</tt> set to <tt>EINTR</tt>.</P>
</blockquote>

<pre>
   <span class="docEmphItalicAlt">timeout</span> == 0
</pre><br>

<blockquote>
<p class="docText">Don't wait. All the specified descriptors are tested, and we return immediately. This is a way to poll the system to find out the status of multiple descriptors, without blocking in the call to <tt>poll</tt>.</P>
</blockquote>

<pre>
   <span class="docEmphItalicAlt">timeout</span> &gt; 0
</pre><br>

<blockquote>
<p class="docText">Wait <span class="docEmphasis">timeout</span> milliseconds. We return when one of the specified descriptors is ready or when the <span class="docEmphasis">timeout</span> expires. If the <span class="docEmphasis">timeout</span> expires before any of the descriptors is ready, the return value is 0. (If your system doesn't provide millisecond resolution, <span class="docEmphasis">timeout</span> is rounded up to the nearest supported value.)</P>
</blockquote>
<p class="docText">It is important to realize the difference between an end of file and a hangup. If we're entering data from the terminal and type the end-of-file character, <tt>POLLIN</tt> is <a name="idd1e105690"></a><a name="idd1e105693"></a><a name="idd1e105696"></a><a name="idd1e105699"></a><a name="idd1e105702"></a><a name="idd1e105707"></a><a name="idd1e105710"></a><a name="idd1e105715"></a><a name="idd1e105718"></a><a name="idd1e105723"></a><a name="idd1e105728"></a><a name="idd1e105733"></a><a name="idd1e105738"></a><a name="idd1e105741"></a><a name="idd1e105744"></a><a name="idd1e105747"></a><a name="idd1e105752"></a><a name="idd1e105757"></a>turned on so we can read the end-of-file indication (<tt>read</tt> returns 0). <tt>POLLHUP</tt> is not turned on in <tt>revents</tt>. If we're reading from a modem and the telephone line is hung up, we'll receive the <tt>POLLHUP</tt> notification.</P>
<p class="docText">As with <tt>select</tt>, whether a descriptor is blocking or not doesn't affect whether <tt>poll</tt> blocks.</P>

<a name="ch14lev2sec16"></a>
<h4 class="docSection2Title">Interruptibility of <tt>select</tt> and <tt>poll</tt></H4>
<p class="docText">When the automatic restarting of interrupted system calls was introduced with 4.2BSD (<a class="docLink" href="ch10lev1sec5.html#ch10lev1sec5">Section 10.5</a>), the <tt>select</tt> function was never restarted. This characteristic continues with most systems even if the <tt>SA_RESTART</tt> option is specified. But under SVR4, if <tt>SA_RESTART</tt> was specified, even <tt>select</tt> and <tt>poll</tt> were automatically restarted. To prevent this from catching us when we port software to systems derived from SVR4, we'll always use the <tt>signal_intr</tt> function (<a class="docLink" href="ch10lev1sec14.html#ch10fig19">Figure 10.19</a>) if the signal could interrupt a call to <tt>select</tt> or <tt>poll</tt>.</P>
<blockquote>
<p class="docText">None of the implementations described in this book restart <tt>poll</tt> or <tt>select</tt> when a signal is received, even if the <tt>SA_RESTART</tt> flag is used.</p>
</blockquote>


<UL></UL></td></tr></table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch14lev1sec4.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch14lev1sec6.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
</body></html><br>
<table width="100%" cellspacing="0" cellpadding="0"
style="margin-top: 0pt; border-collapse: collapse;"> 
<tr> <td align="right" style="background-color=white; border-top: 1px solid gray;"> 
<a href="http://www.zipghost.com/" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">The CHM file was converted to HTM by Trial version of <b>ChmD<!--152-->ecompiler</b>.</a>
</TD>
</TR><tr>
<td align="right" style="background-color=white; "> 
<a href="http://www.etextwizard.com/download/cd/cdsetup.exe" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">Download <b>ChmDec<!--152-->ompiler</b> at: http://www.zipghost.com</a>
</TD></tr></table>
